package com.gkzf.ai.module.crm.util.simpleCredit;

import com.gkzf.ai.module.crm.controller.admin.simpleCredit.vo.CreditCardAccount;

import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 通用计算方法 计算 数量 金融
 * 支持 单集合-Predicate(判断)-Function(取值)
 * 也支持 双集合-双Predicate(判断)-双Function(取值) 累加
 */
public class AccountUtils { // 或者放在 SimpleCreditExtract 中

    private AccountUtils() {}
    /**
     * 通用方法，用于统计列表中满足特定条件的账户数量。
     * @param accountList 任何元素类型实现了 K 接口的列表
     * @param overdueAccountList 任何元素类型实现了 T 接口的列表
     * @param predicateT   一个可以测试 T 类型对象的 Predicate
     * @param predicateK   一个可以测试 K 类型对象的 Predicate
     * @param <T>         一个泛型类型，它必须是 LoanAccount 或其子类型
     * @return 满足条件的元素数量
     */
    public static <K,T extends CreditCardAccount> int countAccountsByPredicate(List<K> accountList, List<T> overdueAccountList, Predicate<? super T> predicateT, Predicate<? super K> predicateK) {
        long count = accountList.stream()
                .filter(predicateK)
                .count();

        long overdueCount = overdueAccountList.stream()
                .filter(predicateT)
                .count();
        return (int) (count+overdueCount);
    }


    /**
     * 通用方法，用于统计列表中满足特定条件的账户数量。
     * @param overdueAccountList 任何元素类型实现了 T 接口的列表
     * @param predicateT   一个可以测试 T 类型对象的 Predicate
     * @param <T>         一个泛型类型，它必须是 LoanAccount 或其子类型
     * @return 满足条件的元素数量
     */
    public static <T extends CreditCardAccount> int countAccountsByPredicate(List<T> overdueAccountList, Predicate<? super T> predicateT) {

        long overdueCount = overdueAccountList.stream()
                .filter(predicateT)
                .count();
        return (int) (overdueCount);
    }

    /**
     * 通用方法，用于统计列表中满足特定条件的账户数量。(去重)
     *
     * @param accountList 任何元素类型实现了 K 接口的列表
     * @param overdueAccountList 任何元素类型实现了 T 接口的列表
     * @param getterK 去重字段
     * @param getterT 去重字段
     * @param predicateT   一个可以测试 T 类型对象的 Predicate
     * @param predicateK   一个可以测试 K 类型对象的 Predicate
     * @param <T>         一个泛型类型，它必须是 LoanAccount 或其子类型
     * @return 满足条件的元素数量
     */
    public static <K,T extends CreditCardAccount> int countAccountsByPredicateRepeat(List<K> accountList,
                                                                                   List<T> overdueAccountList,
                                                                                   Function<? super K,?> getterK,
                                                                                   Function<? super T,?> getterT,
                                                                                   Predicate<? super T> predicateT,
                                                                                   Predicate<? super K> predicateK) {
        // 如果需要继续操作，可以再转为Stream
        long count = accountList.stream()
                .filter(predicateK)
                .collect(Collectors.toMap(
                        getterK,
                        Function.identity(),
                        (existing, replacement) -> existing
                )) // 从Map中取出所有的Value (即去重后的Account对象)
                .size();


        long overdueCount = overdueAccountList.stream()
                .filter(predicateT)
                .collect(Collectors.toMap(
                        getterT,
                        Function.identity(),
                        (existing, replacement) -> existing
                )) // 从Map中取出所有的Value (即去重后的Account对象)
                .size();
        return (int) (count+overdueCount);
    }

    /**
     * 通用方法，用于统计列表中满足特定条件的账户数量。
     *
     * @param accountList 任何元素类型实现了 T 接口的列表
     * @param overdueAccountList 任何元素类型实现了 T 接口的列表
     * @param getterT   一个可以测试 T 类型对象的 Predicate
     * @param getterK   一个可以测试 K 类型对象的 Predicate
     * @param predicateK 一个条件判断 K 类型对象 Function
     * @param predicateT 一个条件判断 T 类型对象 Function
     * @param <T>         一个泛型类型，它必须是 LoanAccount 或其子类型
     * @return 满足条件的元素数量
     */
    public static <K,T extends CreditCardAccount> BigDecimal countAccountsByPredicate(List<T> accountList, Predicate<? super T> predicateT,Function<? super T, BigDecimal> getterT,
                                                                                      List<K> overdueAccountList, Predicate<? super K> predicateK, Function<? super K, BigDecimal> getterK) {
        BigDecimal money = accountList.stream()
                .filter(predicateT)
                .map(getterT)
                .map(item -> Optional.ofNullable(item).orElse(BigDecimal.ZERO))
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal overdueMoney = overdueAccountList.stream()
                .filter(predicateK)
                .map(getterK)
                .map(item -> Optional.ofNullable(item).orElse(BigDecimal.ZERO))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        return money.add(overdueMoney);
    }

    /**
     * 通用方法，用于统计列表中满足特定条件的账户数量。
     *
     * @param accountList 任何元素类型实现了 T 接口的列表
     * @param getterT   一个可以测试 T 类型对象的 Predicate
     * @param predicateT 一个条件判断 T 类型对象 Function
     * @param <T>         一个泛型类型，它必须是 LoanAccount 或其子类型
     * @return 满足条件的元素数量
     */
    public static <T extends CreditCardAccount> BigDecimal countAccountsByPredicate(List<T> accountList, Predicate<? super T> predicateT, Function<? super T, BigDecimal> getterT) {
        return accountList.stream()
                .filter(predicateT)
                .map(getterT)
                .map(item -> Optional.ofNullable(item).orElse(BigDecimal.ZERO))
                .reduce(BigDecimal.ZERO, BigDecimal::add);

    }
}